#!/usr/bin/python
# -*- coding: koi8-r -*-
## OJAB: Open-source Jabber Automatic Bot by:
##   Boris Kotov aka zLon / Avoozl <admin@avoozl.ru>
##   Dmitry Gribanov aka Incred <onlythegod@gmail.com>
##   Alexey Frolov aka alf <falexey@nm.ru>
##
## Requires an xmpppy library to run.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## Our project page: http://sourceforge.net/projects/ojab/
## Version 0.94 alpha
import os, sys, xmpp, time, iq, speak, wtfdfn
global vername, handlers, ver_queue, time_queue, iq_id, skip, messages, admins, commandprefix, speak_word_db, speak_wordpo_db, jid_, pass_, res_, conf_
from ojab_config import *
skip={}

iq.messages=messages
wtfdfn.messages=messages
speak.lpo=lpo

if speak_word_db:
    global ws, lofs, cpos, cpo, po
    ws, lofs, cpos, cpo, po=speak.dbopen(speak_word_db, speak_wordpo_db)
else:
    ws=[]
    cpos=[]
    cpo=[]
    po=[]

def joincmd(conn, msg, args, replyto):
    args=args.split(" ")
    cjoin(conn, args[0], args[1])

def partcmd(conn, msg, args, replyto):
    cpart(conn, args)

def saycmd(conn, msg, args, replyto):
    if args=="":
        conn.send(xmpp.protocol.Message(replyto, messages['prparams']))
    elif args.find("|")==-1:
        conn.send(xmpp.protocol.Message(replyto, messages['prparams']))
    elif skip.has_key(args.split("|",1)[0]):
        conn.send(xmpp.protocol.Message(args.split("|",1)[0], args.split("|",1)[1],'groupchat'))
    else:
        conn.send(xmpp.protocol.Message(args.split("|",1)[0], args.split("|",1)[1]))

def quitcmd(conn, msg, args, replyto):
    raise KeyboardInterrupt

handlers={'version':[iq.versioncmd, None, 0, None], 'ping':[iq.pingcmd, None, 0, None], 'time':[iq.timecmd, None, 0, None], 'wtf':[wtfdfn.wtfone, None, 0, None], 'wtfall':[wtfdfn.wtfall, None, 0, None], 'dfn':[wtfdfn.dfn, None, 0, None], 'join':[joincmd, 2, 1, 1], 'part':[partcmd, 1, 1, 1], 'say':[saycmd, None, 1, 1], 'quit':[quitcmd, 0, 1, 1], 1000:[None, 0, 1, 1]}

def checkargs(conn, msg, command, args, replyto):
    if not handlers[command][1]:
        return True
    elif len([elem for elem in args.split(" ") if elem.strip()!=''])==handlers[command][1]:
        return True
    else:
        if msg.getType()=='chat':
            conn.send(xmpp.protocol.Message(replyto, messages['prparams']))
        elif msg.getType()=='groupchat':
            conn.send(xmpp.protocol.Message(replyto, messages['params']%msg.getFrom().getResource(), 'groupchat'))
        return False

def checktype(msg, command):
    if msg.getType()=='groupchat':
        if handlers[command][2]==0: return True
        if handlers[command][2]==1: return False
        if handlers[command][2]==2: return True
    elif msg.getType()=='chat':
        if handlers[command][2]==1: return True
        if handlers[command][2]==0: return False
        if handlers[command][2]==2: return True

def checkadmin(conn, command, replyto, jid, silent=False):
    if not handlers[command][3]: return True
    for j in admins:
        if j.lower()==jid.lower(): return True
    if not silent: conn.send(xmpp.protocol.Message(replyto, messages['prdeny']))
    return False

def cjoin(conn, cname, nick):
    p=xmpp.protocol.Presence('%s/%s'%(cname, nick))
    p.setTag('x',namespace=xmpp.NS_MUC).addChild('history',{'maxchars':'0','maxstanzas':'0'})
    conn.send(p)
    skip[cname]=nick

def cpart(conn, cname):
    conn.send(xmpp.protocol.Presence('%s'%cname, 'unavailable'))
    if skip.has_key(cname): del(skip[cname])

def messageCB(conn, msg):
    sbody=msg.getBody()
    sfrom=msg.getFrom()
    if msg.getType()=='groupchat':
        replyto=("%s@%s"%(sfrom.getNode(), sfrom.getDomain()))
        if skip[replyto]==sfrom.getResource():
            return
    else:
        replyto=("%s@%s/%s"%(sfrom.getNode(), sfrom.getDomain(), sfrom.getResource()))
    if type(sbody) in (str,unicode) and len(sbody)>1:
        if sbody[:len(commandprefix)]==commandprefix:
            if sbody.find(' ')+1: cmd,args=sbody.split(' ',1)
            else: cmd,args=sbody,''
            command=cmd[len(commandprefix):].lower()
            if handlers.has_key(command):
                if checktype(msg, command):
                    if checkadmin(conn, command, replyto, "%s@%s"%(sfrom.getNode(), sfrom.getDomain())):
			if handlers[command][1]:
			    args=" ".join([elem for elem in args.split(" ") if elem.strip()!=''])
                        if checkargs(conn, msg, command, args, replyto): handlers[command][0](conn, msg, args, replyto)
		raise xmpp.NodeProcessed
		return
        if speak_add_db or speak_word_db:
            if msg.getType()=='groupchat':
                if skip.has_key(replyto):
                    if sbody.find(skip[replyto])==0:
                        aitext=sbody[len(skip[replyto]):].strip(":,<>[] ")
                        conn.send(xmpp.protocol.Message(replyto, "%s: %s"%(msg.getFrom().getResource(), speak.sp(ws, lofs, cpos, cpo, po, aitext, speak_add_db)), 'groupchat'))
            elif msg.getType()=='chat':
                conn.send(xmpp.protocol.Message(replyto, speak.sp(ws, lofs, cpos, cpo, po, sbody)))
    raise xmpp.NodeProcessed

def presenceCB(conn, msg):
    ptype=msg.getType()
    pfrom=msg.getFrom()
    pjid="%s@%s"%(pfrom.getNode(), pfrom.getDomain())
    if ptype=='subscribe':
	if checkadmin(conn, 1000, pjid, pjid, True):
	    conn.send(xmpp.protocol.Presence(pfrom, 'subscribed'))
	    conn.send(xmpp.protocol.Presence(pfrom, 'subscribe'))

def StepOn(conn):
    try:
        conn.Process(1)
    except KeyboardInterrupt:
        return 0
    return 1

def GoOn(conn):
    while StepOn(conn):
        pass

jid=xmpp.protocol.JID(jid_)
cl=xmpp.Client(jid.getDomain(),debug=[])
cl.connect()
cl.auth(jid.getNode(),pass_, res_)

cl.RegisterHandler('message', messageCB)
cl.RegisterHandler('presence', presenceCB)
cl.RegisterHandler('iq', iq.versionCB, 'get', xmpp.NS_VERSION)
cl.RegisterHandler('iq', iq.versionresultCB, 'result', xmpp.NS_VERSION)
cl.RegisterHandler('iq', iq.versionerrorCB, 'error', xmpp.NS_VERSION)
cl.RegisterHandler('iq', iq.timeCB, 'get', xmpp.NS_TIME)
cl.RegisterHandler('iq', iq.timeresultCB, 'result', xmpp.NS_TIME)
cl.RegisterHandler('iq', iq.timeerrorCB, 'error', xmpp.NS_TIME)

cl.sendInitPresence()
for jidc in conf_:
    cjoin(cl, jidc, conf_[jidc])
GoOn(cl)
cl.disconnect()
